using CfgTable;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using System.Collections.Generic;

namespace IQIGame.Onigao.GamePlay
{
    public class UIFormationPopup : UIBaseWindow
    {
        /// <summary>
        /// 静态配置
        /// </summary>
        private static UICreateConfig _createConfig = new()
        {
            prefabName = nameof(UIFormationPopup),
            layer = EUILayer.Pop,
            activeBlurBg = true,
        };

        /// <summary>
        /// 创建UI的配置
        /// </summary>
        public override IUICreateConfig createConfig => _createConfig;

        #region Template Generate,don't modify
        protected partial class UIB_UIFormationPopup
        {
            #region ObjectBinding Generate
            public IQIGame.Onigao.Framework.ExButton backGroundBtnClose { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton btnTransposition { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton btnClose { protected set; get; }
            public UnityEngine.GameObject leftHero { protected set; get; }
            public IQIGame.Onigao.Framework.ExRawImage heroImage { protected set; get; }
            public IQIGame.Onigao.Framework.ExText textHeroName { protected set; get; }
            public UnityEngine.GameObject heroLv { protected set; get; }
            public IQIGame.Onigao.Framework.ExArtSpriteNum classTypeIcon { protected set; get; }
            public IQIGame.Onigao.Framework.ExArtSpriteNum attributeTypeIcon { protected set; get; }
            public UnityEngine.GameObject star { protected set; get; }
            public UnityEngine.GameObject attMould { protected set; get; }
            public UnityEngine.GameObject fightPower { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton btnDetail { protected set; get; }
            public UnityEngine.GameObject skillMould { protected set; get; }
            public UnityEngine.GameObject equipItem { protected set; get; }
            public UnityEngine.GameObject petItem { protected set; get; }
            public UnityEngine.GameObject leftEmpty { protected set; get; }
            public UnityEngine.GameObject heroMould { protected set; get; }
            public UnityEngine.GameObject toggleFilter { protected set; get; }
            public UnityEngine.UI.ExLoopVerticalScrollRect loopChooseScroll { protected set; get; }
            public UnityEngine.GameObject rightChooseEmpty { protected set; get; }
            public virtual void InitBinding(ObjectBinding __binding)
            {
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("backGroundBtnClose", out var __tbv0);
                this.backGroundBtnClose = __tbv0;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("btnTransposition", out var __tbv1);
                this.btnTransposition = __tbv1;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("btnClose", out var __tbv2);
                this.btnClose = __tbv2;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("leftHero", out var __tbv3);
                this.leftHero = __tbv3;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExRawImage>("heroImage", out var __tbv4);
                this.heroImage = __tbv4;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExText>("textHeroName", out var __tbv5);
                this.textHeroName = __tbv5;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("heroLv", out var __tbv6);
                this.heroLv = __tbv6;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExArtSpriteNum>("classTypeIcon", out var __tbv7);
                this.classTypeIcon = __tbv7;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExArtSpriteNum>("attributeTypeIcon", out var __tbv8);
                this.attributeTypeIcon = __tbv8;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("star", out var __tbv9);
                this.star = __tbv9;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("attMould", out var __tbv10);
                this.attMould = __tbv10;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("fightPower", out var __tbv11);
                this.fightPower = __tbv11;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("btnDetail", out var __tbv12);
                this.btnDetail = __tbv12;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("skillMould", out var __tbv13);
                this.skillMould = __tbv13;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("equipItem", out var __tbv14);
                this.equipItem = __tbv14;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("petItem", out var __tbv15);
                this.petItem = __tbv15;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("leftEmpty", out var __tbv16);
                this.leftEmpty = __tbv16;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("heroMould", out var __tbv17);
                this.heroMould = __tbv17;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("toggleFilter", out var __tbv18);
                this.toggleFilter = __tbv18;
                __binding.TryGetVariableValue<UnityEngine.UI.ExLoopVerticalScrollRect>("loopChooseScroll", out var __tbv19);
                this.loopChooseScroll = __tbv19;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("rightChooseEmpty", out var __tbv20);
                this.rightChooseEmpty = __tbv20;
            }
            #endregion ObjectBinding Generate 
        }
        #endregion Template Generate,don't modify

        #region fields & properties
        ListScrollAdapter<UIN_FormationPopupHero> heroForms = null;
        ListScrollAdapter<UIN_FormationPopHeroFilter> tabOwnHeros = null;
        LoopScrollAdapter<UIN_CommonHeroHead> loopOwnHeros = null;
        UIN_CommonTitleValue lv, ftPower;
        ListScrollAdapter<UIN_CommonAttribute> attrs = null;
        ListScrollAdapter<UIN_CommonDarkLight> stars = null;
        ListScrollAdapter<UIN_HeroSkillCell> skills = null;
        UIN_CommonPet petUnit = null;
        ListScrollAdapter<UIN_OneItem> equips = null;

        FormationData formData = null;
        int selectFormId = -1;
        int selectFormPos = -1;
        int selectFormPosHeroCid = -1;
        HeroData selectHeroData = null;
        int selectHeroCid = -1;
        List<long> selectHeroWearEquipIds = ListPool<long>.Get();
        List<HeroData> ownHeroList = new(2);
        int btnTranspositionState = 0;

        protected UIB_UIFormationPopup ui { get; set; }
        #endregion

        protected override void BeforeInit()
        {
            ui = new UIB_UIFormationPopup();
            ui.InitBinding(this.csObjBind);
        }

        protected override void OnInit()
        {
            this.heroForms = this.InitListScroll<UIN_FormationPopupHero>(this.ui.heroMould, this.OnFormChanged);
            this.heroForms.InitUnitSelected(UnitSelectType.ByExButton, this.OnFormSelected);

            this.tabOwnHeros = this.InitListScroll<UIN_FormationPopHeroFilter>(this.ui.toggleFilter, this.OnTabChanged);
            this.tabOwnHeros.InitUnitSelected(UnitSelectType.ByExToggle, this.OnTabSelected);

            this.loopOwnHeros = this.InitLoopScroll<UIN_CommonHeroHead>(this.ui.loopChooseScroll, this.OnHeroChanged);
            this.loopOwnHeros.InitUnitSelected(UnitSelectType.ByExButton, this.OnHeroSelected);

            #region Hero Info
            this.lv = this.InitChildNode<UIN_CommonTitleValue>(this.ui.heroLv);
            this.ftPower = this.InitChildNode<UIN_CommonTitleValue>(this.ui.fightPower);
            this.attrs = this.InitListScroll<UIN_CommonAttribute>(this.ui.attMould, this.OnAttrChanged);
            this.stars = this.InitListScroll<UIN_CommonDarkLight>(this.ui.star, this.OnStarChanged);
            this.skills = this.InitListScroll<UIN_HeroSkillCell>(this.ui.skillMould, this.OnSkillChanged);
            this.ui.btnDetail.onClick.AddListener(this.OnClickBtnHeroDetail);

            this.petUnit = this.InitChildNode<UIN_CommonPet>(this.ui.petItem);
            this.equips = this.InitListScroll<UIN_OneItem>(this.ui.equipItem, this.OnEquipChanged);
            #endregion

            this.ui.leftEmpty.SetActive(false);
            this.ui.leftHero.SetActive(false);

            this.ui.btnTransposition.onClick.AddListener(this.OnClickBtnTransposition);
            this.ui.backGroundBtnClose.onClick.AddListener(this.Close);
            this.ui.btnClose.onClick.AddListener(this.Close);
        }

        protected override void OnShow()
        {

        }

        protected override void OnHide()
        {

        }

        protected override void OnDispose()
        {
            this.ClearData();
        }

        void ClearData()
        {
            this.formData = null;
            this.selectFormId = -1;
            this.selectFormPos = -1;
            this.selectFormPosHeroCid = -1;
            this.selectHeroData = null;
            this.selectHeroCid = -1;
            if (this.selectHeroWearEquipIds != null)
            {
                ListPool<long>.Put(this.selectHeroWearEquipIds);
                this.selectHeroWearEquipIds = null;
            }
            this.ownHeroList.Clear();
        }

        protected override void OnShow(UIBaseData data)
        {
            UD_FormationPopup d = (UD_FormationPopup)data;
            int formId = d.formId;
            int selectFormPos = d.formPos;
            int selectHeroCid = d.selectHeroCid;

            var playData = GameDataCenter.PlayerData;
            var formData = playData.formation.GetFormation(formId);
            var formHeroData = formData.GetFormationHeroData(selectFormPos);
            this.SetFormHeroData(formHeroData);
            playData.hero.FindHeroDataByCid(selectHeroCid, out var heroData);
            this.SetSelectHeroData(heroData);
            this.ShowFormSlots();
        }

        protected override UIBaseData OnGetLeaveData()
        {
            return UD_FormationPopup.Create(selectFormId, selectFormPos, selectHeroCid);
        }

        void SetFormHeroData(FormationHeroData data)
        {
            this.formData = data.belong;
            this.selectFormPos = data.pos;
            this.selectFormPosHeroCid = data.cid;

            this.selectFormId = this.formData.formId;
        }

        void SetSelectHeroData(HeroData heroData)
        {
            this.selectHeroData = heroData;
            this.selectHeroCid = heroData?.cid ?? -1;

            this.selectHeroWearEquipIds.Clear();
            if (heroData != null)
            {
                foreach (var equipId in heroData.equips.Values)
                {
                    selectHeroWearEquipIds.Add(equipId);
                }
            }
        }

        void ShowFormSlots()
        {
            int cnt = APIUIFormation.FormHeroAllCount;
            int selectedIndex = this.GetSelectFormSlotIndex();
            this.heroForms.RefillCells(cnt, selectedIndex);
        }

        int GetSelectFormSlotIndex()
        {
            for (int i = 0, cnt = APIUIFormation.FormHeroAllCount; i < cnt; i++)
            {
                int nPos = APIUIFormation.GetFormHeroPosByIndex(i);
                if (nPos == this.selectFormPos)
                {
                    return i;
                }
            }
            return -1;
        }

        void OnFormChanged(UIN_FormationPopupHero item, int index)
        {
            int pos = APIUIFormation.GetFormHeroPosByIndex(index);
            var posData = this.formData.GetFormationHeroData(pos);
            item.Show(posData);
        }

        void OnFormSelected(int index, UIN_FormationPopupHero item)
        {
            int pos = APIUIFormation.GetFormHeroPosByIndex(index);
            var posData = this.formData.GetFormationHeroData(pos);

            this.selectFormPos = posData.pos;
            this.selectFormPosHeroCid = posData.cid;

            int cnt = (int)EM_HeroConst.MaxLength;
            this.tabOwnHeros.RefillCells(cnt, 0);
        }

        void OnTabChanged(UIN_FormationPopHeroFilter item, int index)
        {
            item.Show(index);
        }

        void OnTabSelected(int index, UIN_FormationPopHeroFilter item)
        {
            this.InitOwnHeros(index);
            int _seleIndex = this.GetSelectHeroIndex(this.ownHeroList);
            int cnt = this.ownHeroList.Count;
            this.loopOwnHeros.RefillCellsAndSelected(cnt, _seleIndex);
            this.ui.rightChooseEmpty.SetActive(cnt == 0);
        }

        void InitOwnHeros(int tab)
        {
            var list = HeroModule.Instance.GetOwnHeros(tab, this.SortOwnListFunc);
            this.ownHeroList.Clear();
            this.ownHeroList.AddRange(list);
        }


        int SortOwnListFunc(HeroData a, HeroData b)
        {
            bool isHasA = this.formData.GetFormationHeroDataByHeroCid(a.cid) != null;
            bool isHasB = this.formData.GetFormationHeroDataByHeroCid(b.cid) != null;
            if (isHasA != isHasB)
                return isHasA ? -1 : 1;

            if (a.level != b.level)
                return a.level > b.level ? -1 : 1;
            if (a.exp != b.exp)
                return a.exp > b.exp ? -1 : 1;
            if (a.star != b.star)
                return a.star > b.star ? -1 : 1;
            return a.cid < b.cid ? -1 : 1;
        }

        int GetSelectHeroIndex(List<HeroData> ownList)
        {
            if (this.selectHeroCid > 0)
            {
                for (int i = 0, cnt = ownList.Count; i < cnt; i++)
                {
                    if (this.selectHeroCid == ownList[i].cid)
                    {
                        return i;
                    }
                }
            }
            return -1;
        }

        void OnHeroChanged(UIN_CommonHeroHead item, int index)
        {
            var heroData = this.ownHeroList[index];
            var formPos = this.formData.GetFormationHeroPosByHeroCid(heroData.cid);
            bool isWorking = formPos != -1;
            bool isCurrPos = isWorking && this.selectFormPos == formPos;
            item.ShowFormation(heroData, isCurrPos, isWorking);
        }

        void OnHeroSelected(int index, UIN_CommonHeroHead item)
        {
            HeroData heroData = (item != null) ? this.ownHeroList[index] : null;
            this.SetSelectHeroData(heroData);

            this.ShowChooseHero();
        }

        void ShowChooseHero()
        {
            HeroData heroData = this.selectHeroData;
            bool isHasSelectHero = heroData != null;
            this.ui.leftEmpty.SetActive(!isHasSelectHero);
            this.ui.leftHero.SetActive(isHasSelectHero);
            this.ui.btnTransposition.SetActive(isHasSelectHero);
            if (heroData == null)
                return;
            int maxLevel = heroData.maxLv;

            this.ui.textHeroName.text = HeroModule.Instance.GetHeroName(heroData);
            CfgHero cfgHero = heroData.cfgData;

            this.ui.classTypeIcon.SetInt(cfgHero.HeroClass);
            this.ui.attributeTypeIcon.SetInt(cfgHero.HeroElementType);

            CfgHeroSkin cfgSkin = heroData.cfgSkin;
            this.SetRawImageTexture(this.ui.heroImage, cfgSkin.HeroFormationImage_fullPath);

            string strTitle = APIUIConst.GetGreaterAddStr(heroData.level);
            string strValue = "/" + maxLevel;
            this.lv.Show(strValue, strTitle);

            this.stars.RefillCells(APIUIConst.HeroDefautMaxStar);

            int cntSkill = APIUIHeroInfo.DefaultSkillCount;
            this.skills.RefillCells(cntSkill);

            this.ftPower.Show(heroData.fightPower.ToString());

            var attrs = APIUIHeroInfo.BasicAttributeIds;
            this.attrs.RefillCells(attrs.Length);

            this.ShowChooseHeroPet();
            this.ShowChooseHeroEquips();
            this.ShowChooseHeroBtn();
        }

        void ShowChooseHeroPet()
        {
            var petId = this.selectHeroData.petId;
            var petData = GameDataCenter.PlayerData.pet;
            petData.TryGetValue(petId, out var pet);
            this.petUnit.Show(pet);
        }

        void ShowChooseHeroEquips()
        {
            int cntEquip = this.selectHeroWearEquipIds.Count;
            this.equips.RefillCells(cntEquip);
        }

        void OnEquipChanged(UIN_OneItem item, int index)
        {
            long equipId = this.selectHeroWearEquipIds[index];
            GameDataCenter.PlayerData.item.TryGetItem(equipId, out var itemData);
            ItemEquipmentData equipItem = (ItemEquipmentData)itemData;
            item.ShowEquip(equipItem);
        }

        void ShowChooseHeroBtn()
        {
            int btnState = 0;
            if (this.selectFormPosHeroCid == this.selectHeroCid)
                btnState = 2;
            else if (this.formData.GetFormationHeroDataByHeroCid(this.selectHeroCid) != null)
                btnState = 1;
            this.btnTranspositionState = btnState;
            this.ui.btnTransposition.text = APIUIFormation.GetFormPopBtnText(btnState);
        }

        void OnAttrChanged(UIN_CommonAttribute item, int index)
        {
            var attrCid = APIUIHeroInfo.BasicAttributeIds[index];
            var attrVal = this.selectHeroData.GetAttr(attrCid);
            item.Show(attrCid, attrVal);
        }

        void OnStarChanged(UIN_CommonDarkLight item, int index)
        {
            int nCurr = index;
            int bigStar = -1;
            if (this.selectHeroData.cfgStar != null)
            {
                bigStar = this.selectHeroData.cfgStar.BigStar - 1;
            }
            bool isLight = (bigStar >= nCurr);
            item.Show(isLight);
        }
        void OnSkillChanged(UIN_HeroSkillCell item, int index)
        {
            var cfgHero = this.selectHeroData.cfgData;
            int skillId = cfgHero.DefaultSkill[index];
            HeroSkill heroSkill = this.selectHeroData.skills[skillId];
            item.Show(heroSkill);
        }

        void OnClickBtnHeroDetail()
        {
            UD_HeroInfo ud = UD_HeroInfo.NewFromPool().Sync(this.selectHeroData, false);
            this.OpenUI<UIHeroInfo>(ud);
        }

        void OnClickBtnTransposition()
        {
            int heroCid = this.btnTranspositionState == 2 ? 0 : this.selectHeroCid;
            if (FormationModule.Instance.IsDefaultFormation(this.selectFormId))
            {
                int cnt = FormationModule.Instance.GetCountRegularHero(this.selectFormId);
                var formPos = this.formData.GetFormationHeroPosByHeroCid(this.selectHeroCid);
                var formPosCurr = this.selectFormPos;
                if (cnt <= 1 && ((formPosCurr >= APIUIFormation.FormBenchHeroStartPos && this.selectFormPosHeroCid <= 0 && this.btnTranspositionState == 1) || (this.btnTranspositionState == 2 && formPos < APIUIFormation.FormBenchHeroStartPos)))
                {
                    var cid = APIUIFormation.GetTipNoticeCid4BtnClick(2);
                    NoticeModule.ShowNoticeNoCall(cid);
                    return;
                }
            }
            this.OnClickBtnTranspositionAsync(heroCid).Forget();
        }

        async UniTaskVoid OnClickBtnTranspositionAsync(int heroCid)
        {
            var result = await FormationModule.NetCore.CS_setHero(this.selectFormId, this.selectFormPos, heroCid);
            if (result.IsSuccess)
            {
                this.RefreshAfterSetHeorResponse();
            }
        }

        void RefreshAfterSetHeorResponse()
        {
            this.heroForms.RefreshCells();
            this.loopOwnHeros.RefreshCells();
            this.ShowChooseHeroBtn();
        }
    }
}
